package io.github.andeibuite.clip.core.account

import io.github.nishikigii.criterionkt.basic.version.Edition
import io.github.nishikigii.criterionkt.utils.browser.Browser
import java.io.Serializable
import java.net.URI
import java.nio.charset.StandardCharsets
import java.security.MessageDigest
import java.util.Date
import java.util.UUID

/**
 * minecraft player account.
 */
@Edition(2024u)
data class Account (

	/**
	 * minecraft player name.
	 */
	val name: String,

	/**
	 * minecraft authentication universally unique identifier.
	 */
	val uuid: UUID,

	/**
	 * minecraft authentication token.
	 */
	val token: String,

	/**
	 * authentication source kind.
	 */
	val kind: String,


	/**
	 * date after which the account expires (null for no expiration).
	 */
	val expiration: Date?

): Serializable
{
	companion object
	{

		/**
		 * none authentication server account.
		 * its uuid generated with player name as seed.
		 * the token is obtained by removing illegal characters from the uuid.
		 * see the documentation for more details.
		 */
		fun offline( name: String ): Account
		{
			val uuid = try {
				val namespace = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
				val inputBytes = name.toByteArray(StandardCharsets.UTF_8)
				val sha1 = MessageDigest.getInstance("SHA-1")
				val hashBytes = sha1.digest(inputBytes)
				val mostSigBits = namespace.mostSignificantBits
				val leastSigBits = hashBytes[0].toLong() and 0xFFL shl 56 or
						(hashBytes[1].toLong() and 0xFFL shl 48) or
						(hashBytes[2].toLong() and 0xFFL shl 40) or
						(hashBytes[3].toLong() and 0xFFL shl 32) or
						(hashBytes[4].toLong() and 0xFFL shl 24) or
						(hashBytes[5].toLong() and 0xFFL shl 16) or
						(hashBytes[6].toLong() and 0xFFL shl 8) or
						(hashBytes[7].toLong() and 0xFFL)
				UUID(mostSigBits, leastSigBits)
			} catch (exception: Exception) { throw exception }
			return Account( name, uuid, "token","offline", expiration = null )
		}
		

		/**
		 * create accounts with microsoft oath 2.0.
		 * the implementation of this function differs from microsoft().
		 * callers needed to provide redirecting url of login website!
		 * see documentation for more details.
		 */
		fun microsoft(): Account
		{
			Browser.openURI(URI("https://login.live.com/oauth20_authorize.srf?client_id=00000000402b5328&response_type=code&scope=service%3A%3Auser.auth" +
					".xboxlive" +
					".com%3A%3AMBI_SSL&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf"))
			// TODO 未实现的账号创建: 微软OAuth2
			return offline("PlayerName")
		}

	}

}
